package LimitedTimeGame.Day_0228;

/**
 * @author zxc
 * @date 2023/02/28 11:04
 **/

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * 题目 ：
 * 题目详述 ：
 * 给你一个类：
 * class FooBar {
 *   public void foo() {
 *       for (int i = 0; i < n; i++) {
 *             print("foo");
 *     }
 *   }
 *
 *   public void bar() {
 *           for (int i = 0; i < n; i++) {
 *                  print("bar");
 *      }
 *   }
 * }
 *
 * 两个不同的线程将会共用一个 FooBar实例：
 * 线程 A 将会调用foo()方法，而
 * 线程 B 将会调用bar()方法
 * 请设计修改程序，以确保 "foobar" 被输出 n 次。
 *
 * 提示：
 * 1 <= n <= 1000
 *
 */
public class FooBar {
    /**
     * 思路 ：
     * 阻塞队列BlockingQueue;
     * ===>
     * 即，维护两个阻塞队列，供foo线程和bar线程进行使用;
     * （1）若是foo线程所维护的阻塞队列中有资源的话，则会选择将其取出 && 执行foo方法 && 将该资源存放到bar线程所维护的阻塞队列中;
     * （2）若是bar线程所维护的阻塞队列中有资源的话，则会选择将其取出 && 执行bar方法 && 将该资源存放到foo线程所维护的阻塞队列中;
     *
     */
    private int n;
    BlockingQueue<Integer> fooBlockingQueue = new LinkedBlockingQueue<>(1);
    BlockingQueue<Integer> barBlockingQueue = new LinkedBlockingQueue<>(1);

    public FooBar(int n) {
        this.n = n;
        fooBlockingQueue.add(1);
    }

    public void foo(Runnable printFoo) throws InterruptedException {

        for (int i = 0; i < n; i++) {
            fooBlockingQueue.take();
            printFoo.run();
            barBlockingQueue.put(1);
        }
    }

    public void bar(Runnable printBar) throws InterruptedException {

        for (int i = 0; i < n; i++) {
            barBlockingQueue.take();
            printBar.run();
            fooBlockingQueue.put(1);
        }
    }
}
